#pragma once

#include <iostream>
#include "MatrixParser.h"

template <typename T>
class Matrix
{

private:
	//private members
	T ** data;
	unsigned rows, cols, elements;
	const char * input;

public:
	//constructors and destructors
	Matrix();
	Matrix(unsigned r, unsigned c);
	Matrix(const char * str);
	virtual ~Matrix();
	Matrix(const Matrix<T> & m);

	//operators
	T & operator() (unsigned r, unsigned c);
	T operator() (unsigned r, unsigned c) const;

	// friend operators
	Matrix<T> & operator= (const Matrix<T> & m);
	Matrix<T> operator+ (const Matrix<T> & m);

	// friend operators (for other types)
	template <typename T1>
	friend std::ostream & operator<< (std::ostream & os, const Matrix<T1> & m);
	template <typename T1>
	friend Matrix<T1> operator+ (const Matrix<T1> & m, const T1 & t);
	template <typename T1>
	friend Matrix<T1> operator- (const Matrix<T1> & m, const T1 & t);

	//custom methods;
	void random();
	void clear();
	const unsigned getRows() const;
	const unsigned getCols() const;

	//flags
	bool memoryAllocated;
	bool isEmpty;
	bool exceptionOccured;

	//templated friend class
	template <typename T1>
	friend class MatrixParser;
};
